<html lang="en">

<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Java---锁 - bravo</title>
<link rel="shortcut icon" href="https://JoyZgq.github.io/favicon.ico">
<link href="https://cdn.jsdelivr.net/npm/remixicon@2.2.0/fonts/remixicon.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/animate.css@3.7.2/animate.min.css">
<link rel="stylesheet" href="https://JoyZgq.github.io/media/css/tailwind.css">
<link rel="stylesheet" href="https://JoyZgq.github.io/styles/main.css">
<link rel="alternate" type="application/atom+xml" title="Java---锁 - bravo - Atom Feed" href="https://JoyZgq.github.io/atom.xml">


  <script async src="https://www.googletagmanager.com/gtag/js?id=UA-164181119-1"></script>
  <script>
    window.dataLayer = window.dataLayer || [];
    function gtag(){dataLayer.push(arguments);}
    gtag('js', new Date());
  
    gtag('config', 'UA-164181119-1');
  </script>
    

  <meta name="description" content="
并发是编程重要的手段，更好的运用并发就必须理解各种锁的区别？

分类

公平锁、非公平锁
可重入锁
独享锁，共享锁
互斥锁，读写锁
乐观锁，悲观锁
分段锁
偏向锁，轻量级锁，重量级锁
自旋锁


公平锁、非公平锁

公平锁：申请锁的顺序，..." />
  <meta property="og:title" content="Java---锁 - bravo">
  <meta property="og:description" content="
并发是编程重要的手段，更好的运用并发就必须理解各种锁的区别？

分类

公平锁、非公平锁
可重入锁
独享锁，共享锁
互斥锁，读写锁
乐观锁，悲观锁
分段锁
偏向锁，轻量级锁，重量级锁
自旋锁


公平锁、非公平锁

公平锁：申请锁的顺序，..." />
  <meta property="og:type" content="articles">
  <meta property="og:url" content="https://JoyZgq.github.io/post/5DDpUu6H-/" />
  <meta property="og:image" content="https://JoyZgq.github.io/post-images/5DDpUu6H-.webp">
  <meta property="og:image:height" content="630">
  <meta property="og:image:width" content="1200">
  <meta name="twitter:title" content="Java---锁 - bravo">
  <meta name="twitter:description" content="
并发是编程重要的手段，更好的运用并发就必须理解各种锁的区别？

分类

公平锁、非公平锁
可重入锁
独享锁，共享锁
互斥锁，读写锁
乐观锁，悲观锁
分段锁
偏向锁，轻量级锁，重量级锁
自旋锁


公平锁、非公平锁

公平锁：申请锁的顺序，...">
  <meta name="twitter:card" content="summary_large_image">
  <link rel="canonical" href="https://JoyZgq.github.io/post/5DDpUu6H-/">

  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/default-skin/default-skin.css">
 
  
    <link rel="stylesheet" href="https://JoyZgq.github.io/media/css/prism-github.css">
  

  
</head>

<body>
  <div class="antialiased flex flex-col min-h-screen" id="app">
    <a href="https://JoyZgq.github.io" class="fixed top-0 left-0 mt-4 bg-black text-white dark:text-gray-700 dark:bg-yellow-50 dark:hover:bg-black dark:hover:text-white inline-flex p-2 pl-8 hover:text-gray-700 hover:bg-yellow-50 font-bold z-10 transition-fast animated fadeInLeft">
      bravo
    </a>
    <div class="max-w-4xl w-full mx-auto">
      <div class="shadow-box bg-white dark:bg-gray-600 rounded-lg pt-32 md:pt-64 px-4 md:px-8 pb-8 animated fadeIn mb-8">
        <h1 class="text-5xl font-semibold leading-normal pb-8 mb-8 border-b-8 border-gray-700">
          Java---锁
        </h1>
        
          <img src="https://JoyZgq.github.io/post-images/5DDpUu6H-.webp" alt="Java---锁" class="block w-full mb-8">
        
        <div class="mb-8 flex flex-wrap">
          <div class="text-gray-400 text-sm mr-4">2020-05-20 · 5 min read</div>
          
        </div>
        <div class="markdown mb-8" v-pre>
          <blockquote>
<p>并发是编程重要的手段，更好的运用并发就必须理解各种锁的区别？</p>
</blockquote>
<h3 id="分类">分类</h3>
<ul>
<li>公平锁、非公平锁</li>
<li>可重入锁</li>
<li>独享锁，共享锁</li>
<li>互斥锁，读写锁</li>
<li>乐观锁，悲观锁</li>
<li>分段锁</li>
<li>偏向锁，轻量级锁，重量级锁</li>
<li>自旋锁</li>
</ul>
<hr>
<h4 id="公平锁-非公平锁">公平锁、非公平锁</h4>
<ul>
<li>公平锁：申请锁的顺序，先来先得锁</li>
<li>非公平锁：不按照申请顺序，优先级反转或者饥饿现象<br>
  ReentrantLock会默认是非公平锁，非公平锁优点在于吞吐量弄公平锁大<br>
  对于Synchronized而言，也是一种非公平锁。由于其并不像ReentrantLock是通过AQS的来实现线程调度，所以并没有任何办法使其变成公平锁。</li>
</ul>
<h4 id="可重入锁">可重入锁</h4>
<p>  又名递归锁，是指在同一个线程在外层方法获取锁的时候，在进入内层方法会自动获取锁。<br>
- 对于Java ReentrantLock而言, 他的名字就可以看出是一个可重入锁，其名字是Re entrant Lock重新进入锁。<br>
- 对于Synchronized而言，也是一个可重入锁。可重入锁的一个好处是可一定程度避免死锁。</p>
<h4 id="独享锁共享锁">独享锁，共享锁</h4>
<ul>
<li>独享锁是指该锁一次只能被一个线程所持有。</li>
<li>共享锁是指该锁可被多个线程所持有<br>
  对于Java ReentrantLock而言，其是独享锁。但是对于Lock的另一个实现类ReadWriteLock，其读锁是共享锁，其写锁是独享锁。</li>
<li>读锁的共享锁可保证并发读是非常高效的，读写，写读 ，写写的过程是互斥的。</li>
<li>独享锁与共享锁也是通过AQS来实现的，通过实现不同的方法，来实现独享或者共享。<br>
  对于Sychronized而言，当然是独享锁</li>
</ul>
<h4 id="互斥锁读写锁">互斥锁，读写锁</h4>
<p>  上面讲的独享锁/共享锁就是一种广义的说法，互斥锁/读写锁就是具体的实现。<br>
- 互斥锁在Java中的具体实现就是ReentrantLock<br>
- 读写锁在Java中的具体实现就是ReadWriteLock</p>
<h4 id="乐观锁悲观锁">乐观锁，悲观锁</h4>
<p>  乐观锁与悲观锁非具体锁，是指看待并发同步的角度。<br>
- 悲观锁认为对于同一个数据的并发操作，一定是会发生修改的，哪怕没有修改，也会认为修改。因此对于同一个数据的并发操作，悲观锁采取加锁的形式。悲观的认为，不加锁的并发操作一定会出问题。<br>
- 乐观锁则认为对于同一个数据的并发操作，是不会发生修改的。在更新数据的时候，会采用尝试更新，不断重新的方式更新数据。乐观的认为，不加锁的并发操作是没有事情的。<br>
  从上面的描述我们可以看出，悲观锁适合写操作非常多的场景，乐观锁适合读操作非常多的场景，不加锁会带来大量的性能提升。<br>
- 悲观锁在Java中的使用，就是利用各种锁。<br>
- 乐观锁在Java中的使用，是无锁编程，常常采用的是CAS算法，典型的例子就是原子类，通过CAS自旋实现原子操作的更新。</p>
<h4 id="分段锁">分段锁</h4>
<p>  分段锁其实是一种锁的设计，并不是具体的一种锁，对于ConcurrentHashMap而言，其并发的实现就是通过分段锁的形式来实现高效的并发操作。以ConcurrentHashMap来说一下分段锁的含义以及设计思想，ConcurrentHashMap中的分段锁称为Segment，它即类似于HashMap（JDK7与JDK8中HashMap的实现）的结构，即内部拥有一个Entry数组，数组中的每个元素又是一个链表；同时又是一个ReentrantLock（Segment继承了ReentrantLock)。当需要put元素的时候，并不是对整个hashmap进行加锁，而是先通过hashcode来知道他要放在那一个分段中，然后对这个分段进行加锁，所以当多线程put的时候，只要不是放在一个分段中，就实现了真正的并行的插入。但是，在统计size的时候，可就是获取hashmap全局信息的时候，就需要获取所有的分段锁才能统计。</p>
<p>  分段锁的设计目的是细化锁的粒度，当操作不需要更新整个数组的时候，就仅仅针对数组中的一项进行加锁操作。</p>
<h4 id="偏向锁轻量级锁重量级锁">偏向锁，轻量级锁，重量级锁</h4>
<p>  这三种锁是指锁的状态，并且是针对Synchronized。在Java 5通过引入锁升级的机制来实现高效Synchronized。这三种锁的状态是通过对象监视器在对象头中的字段来表明的。<br>
- 偏向锁是指一段同步代码一直被一个线程所访问，那么该线程会自动获取锁。降低获取锁的代价。<br>
- 轻量级锁是指当锁是偏向锁的时候，被另一个线程所访问，偏向锁就会升级为轻量级锁，其他线程会通过自旋的形式尝试获取锁，不会阻塞，提高性能。<br>
- 重量级锁是指当锁为轻量级锁的时候，另一个线程虽然是自旋，但自旋不会一直持续下去，当自旋一定次数的时候，还没有获取到锁，就会进入阻塞，该锁膨胀为重量级锁。重量级锁会让其他申请的线程进入阻塞，性能降低。</p>
<h4 id="自旋锁">自旋锁</h4>
<p>  在Java中，自旋锁是指尝试获取锁的线程不会立即阻塞，而是采用循环的方式去尝试获取锁，这样的好处是减少线程上下文切换的消耗，缺点是循环会消耗CPU。</p>

        </div>
        <!-- Share to Twitter, Weibo, Telegram -->
        <div class="flex items-center">
          <div class="mr-4 flex items-center">
            <i class="ri-share-forward-line text-gray-500"></i>
          </div>
          <div class="px-4 cursor-pointer text-blue-500 hover:bg-blue-100 dark:hover:bg-gray-600 inline-flex" @click="shareToTwitter">
            <i class="ri-twitter-line"></i>
          </div>
          <div class="px-4 cursor-pointer text-red-500 hover:bg-red-100 dark:hover:bg-gray-600 inline-flex" @click="shareToWeibo">
            <i class="ri-weibo-line"></i>
          </div>
          <div class="px-4 cursor-pointer text-indigo-500 hover:bg-indigo-100 dark:hover:bg-gray-600 inline-flex" @click="shareToTelegram">
            <i class="ri-telegram-line"></i>
          </div>
        </div>
      </div>

      
        
          <div id="gitalk-container"></div>
        

        
      

      
        <div id="vlaine-comment"></div>
      

      <footer class="py-12 text-center px-4 md:px-0" v-pre>
  Powered by <a href="https://github.com/getgridea/gridea" target="_blank">Gridea</a>  Made by  <a href="https://github.com/JoyZgq" target="_blank">zgq</a> 🎈❤❤❤🌹
</footer>
    </div>

    <!-- TOC Container -->
    <div class="fixed right-0 bottom-0 mb-16 mr-4 shadow w-8 h-8 rounded-full flex justify-center items-center z-10 cursor-pointer bg-white dark:bg-gray-500 dark:text-gray-200 hover:shadow-lg transition-all animated fadeInRight" @click="showToc = true">
      <i class="ri-file-list-line"></i>
    </div>

    <div class="fixed right-0 top-0 bottom-0 overflow-y-auto w-64 bg-white dark:bg-gray-800 p-4 border-l border-gray-100 dark:border-gray-600 z-10 transition-fast" :class="{ '-mr-64': !showToc }">
      <div class="flex mb-4 justify-end">
        <div class="w-8 h-8 inline-flex justify-center items-center rounded-full cursor-pointer hover:bg-gray-200 dark:hover:bg-gray-600 transition-fast" @click="showToc = false">
          <i class="ri-close-line text-lg"></i>
        </div>
      </div>
      <div class="post-toc-container">
        <ul class="markdownIt-TOC">
<li>
<ul>
<li>
<ul>
<li><a href="#%E5%88%86%E7%B1%BB">分类</a>
<ul>
<li><a href="#%E5%85%AC%E5%B9%B3%E9%94%81-%E9%9D%9E%E5%85%AC%E5%B9%B3%E9%94%81">公平锁、非公平锁</a></li>
<li><a href="#%E5%8F%AF%E9%87%8D%E5%85%A5%E9%94%81">可重入锁</a></li>
<li><a href="#%E7%8B%AC%E4%BA%AB%E9%94%81%E5%85%B1%E4%BA%AB%E9%94%81">独享锁，共享锁</a></li>
<li><a href="#%E4%BA%92%E6%96%A5%E9%94%81%E8%AF%BB%E5%86%99%E9%94%81">互斥锁，读写锁</a></li>
<li><a href="#%E4%B9%90%E8%A7%82%E9%94%81%E6%82%B2%E8%A7%82%E9%94%81">乐观锁，悲观锁</a></li>
<li><a href="#%E5%88%86%E6%AE%B5%E9%94%81">分段锁</a></li>
<li><a href="#%E5%81%8F%E5%90%91%E9%94%81%E8%BD%BB%E9%87%8F%E7%BA%A7%E9%94%81%E9%87%8D%E9%87%8F%E7%BA%A7%E9%94%81">偏向锁，轻量级锁，重量级锁</a></li>
<li><a href="#%E8%87%AA%E6%97%8B%E9%94%81">自旋锁</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>

      </div>
    </div>

    <!-- Back to top -->
    <div class="fixed right-0 bottom-0 mb-4 mr-4 shadow w-8 h-8 rounded-full flex justify-center items-center z-10 cursor-pointer bg-white hover:shadow-lg transition-all dark:bg-gray-500 dark:text-gray-200" @click="backToUp" v-show="scrolled">
      <i class="ri-arrow-up-line"></i>
    </div>
  </div>

  <!-- Root element of PhotoSwipe. Must have class pswp. -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
  <!-- Background of PhotoSwipe. 
        It's a separate element as animating opacity is faster than rgba(). -->
  <div class="pswp__bg">
  </div>
  <!-- Slides wrapper with overflow:hidden. -->
  <div class="pswp__scroll-wrap">
    <!-- Container that holds slides. 
            PhotoSwipe keeps only 3 of them in the DOM to save memory.
            Don't modify these 3 pswp__item elements, data is added later on. -->
    <div class="pswp__container">
      <div class="pswp__item">
      </div>
      <div class="pswp__item">
      </div>
      <div class="pswp__item">
      </div>
    </div>
    <!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
    <div class="pswp__ui pswp__ui--hidden">
      <div class="pswp__top-bar">
        <!--  Controls are self-explanatory. Order can be changed. -->
        <div class="pswp__counter">
        </div>
        <button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
        <button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
        <button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
        <!-- Preloader demo http://codepen.io/dimsemenov/pen/yyBWoR -->
        <!-- element will get class pswp__preloader--active when preloader is running -->
        <div class="pswp__preloader">
          <div class="pswp__preloader__icn">
            <div class="pswp__preloader__cut">
              <div class="pswp__preloader__donut">
              </div>
            </div>
          </div>
        </div>
      </div>
      <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
        <div class="pswp__share-tooltip">
        </div>
      </div>
      <button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
      </button>
      <button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
      </button>
      <div class="pswp__caption">
        <div class="pswp__caption__center">
        </div>
      </div>
    </div>
  </div>
</div>

  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script src="https://JoyZgq.github.io/media/scripts/main.js"></script>
  
  <!-- Code Highlight -->
  
    <script src="https://JoyZgq.github.io/media/prism.js"></script>
    <script>
      Prism.highlightAll()
    </script>
  

  <script src="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe-ui-default.min.js"></script>
  <script>
    //拿到预览框架，也就是上面的html代码
    var pswpElement = document.querySelectorAll('.pswp')[0];
    //定义图片数组变量
    var imgitems;
    /**
    * 用于显示预览界面
    * @param index 图片数组下标
    */
    function viewImg(index) {
      //其它选项这里不做过多阐述，详情见官网
      var pswpoptions = {
        index: parseInt(index, 10), // 开始幻灯片索引。0是第一张幻灯片。必须是整数，而不是字符串。
        bgOpacity: 0.7, // 背景透明度，0-1
        maxSpreadZoom: 3, // 缩放级别，不要太大
      };
      //初始化并打开PhotoSwipe，pswpElement对应上面预览框架，PhotoSwipeUI_Default为皮肤，imgitems为图片数组，pswpoptions为选项
      var gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, imgitems, pswpoptions);
      gallery.init()
    }
    /**
    * 用于添加图片点击事件
    * @param img 图片元素
    * @param index 所属下标（在imgitems中的位置）
    */
    function addImgClick(img, index) {
      img.onclick = function() {
        viewImg(index)
      }
    }
    /**
    * 轮询所有图片，获取src、width、height等数据，加入imgitems，并给图片元素添加事件
    * 最好在onload中执行该方法，本站因放在最底部，所以直接初始化
    * 异步加载图片可在图片元素创建完成后调用此方法
    */
    function initImg() {
      //重置图片数组
      imgitems = [];
      //查找class:markdown 下的所有img元素并遍历
      var imgs = document.querySelectorAll('.markdown img');
      for (var i = 0; i < imgs.length; i++) {
        var img = imgs[i];
        //本站相册初始为loading图片，真实图片放在data-src
        var ds = img.getAttribute("data-src");
        //创建image对象，用于获取图片宽高
        var imgtemp = new Image();
        //判断是否存在data-src
        if (ds != null && ds.length > 0) {
          imgtemp.src = ds
        } else {
          imgtemp.src = img.src
        }
        //判断是否存在缓存
        if (imgtemp.complete) {
          var imgobj = {
            "src": imgtemp.src,
            "w": imgtemp.width,
            "h": imgtemp.height,
          };
          imgitems[i] = imgobj;
          addImgClick(img, i);
        } else {
          console.log('进来了2')
          imgtemp.index = i;
          imgtemp.img = img;
          imgtemp.onload = function() {
            var imgobj = {
              "src": this.src,
              "w": this.width,
              "h": this.height,
            };
            //不要使用push，因为onload前后顺序会不同
            imgitems[this.index] = imgobj
            //添加点击事件
            addImgClick(this.img, this.index);
          }
        }
      }
    }
    //初始化
    initImg();
  </script>
  
    <script type="application/javascript" src="https://unpkg.com/valine"></script>
<script type="application/javascript">
  new Valine({
    el: '#vlaine-comment',
    appId: 'Sy2gsMvGcPQl3gTGsqqYsHW6-gzGzoHsz',
    appKey: 'IpsgegiMUNgRg7l5BVXk6EXM',
    pageSize: 10,
    notify: false,
    avatar: 'mp',
    verify: true,
    placeholder: '客官来都来了，不妨评论一下🌹🐱‍👤',
    visitor: true,
    highlight: false,
    recordIP: true,
  })
</script>
  
  
    
      <link rel="stylesheet" href="https://unpkg.com/gitalk/dist/gitalk.css">
<script type="application/javascript" src="https://unpkg.com/gitalk/dist/gitalk.min.js"></script>

<script type="application/javascript">

  var gitalk = new Gitalk({
    clientID: '83da62f594c23db993f3',
    clientSecret: '9aa795ad06ecb4133721f1acf047ecb1e4f295e8',
    repo: 'GitalkApp',
    owner: 'JoyZgq',
    admin: ['JoyZgq'],
    id: (location.pathname).substring(0, 49),      // Ensure uniqueness and length less than 50
    distractionFreeMode: false  // Facebook-like distraction free mode
  })

  gitalk.render('gitalk-container')

</script>

    
  
</body>

</html>